#ifndef __NOISE_HH__
#define __NOISE_HH__

#include <cstdint>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>

namespace math
{

class Noise
{
public:
    //! @brief 构造函数
    Noise(uint64_t seed, int64_t baseX, int64_t baseY, int64_t size);

    //! @brief 随机函数 
    uint64_t rand11(int64_t v);
    float rand21(int64_t x, int64_t z)
    {
        return static_cast<float>(this->rand11(x) ^ this->rand11(z)) / static_cast<float>(0xffffffffffffffffu);
    }

    //! @brief 缓和曲线计算权重
    static float fade(float t)
    {
        //return t * t * (3.0 - 2.0 * t);
        return t * t * t * (t * (t * 6 - 15) + 10); // 6t^5-15t^4+10t^3
    }

    //! @brief 插值函数
    static float lerp(float val1, float val2, float weight)
    {
        return val1 + (val2 - val1) * weight;
    }

    //! @brief 插值函数
    float interpolation(float x, float z){
        return Noise::lerp(
            Noise::lerp(this->_vertexValue[0], this->_vertexValue[1], Noise::fade(x)),
            Noise::lerp(this->_vertexValue[2], this->_vertexValue[3], Noise::fade(x)),
            Noise::fade(z));
    }

    //! @brief 值噪声函数
    float valueNoise(unsigned int x, unsigned int z)
    {
        return this->interpolation(static_cast<float>(x) / static_cast<float>(this->_size), 
                                   static_cast<float>(z) / static_cast<float>(this->_size));
    }

private:
    int64_t _size;
    const uint64_t _bitNoise1;
    const uint64_t _bitNoise2;
    float _vertexValue[4];
};
}

#endif